#pragma once;

#include "GLFWApp.h"
#include "rigidbody.h"
#include "collisiondata.h"
#include "contact_resolver.h"
#include "collision_primitive.h"
#include <vector>
#include <list>
#include "box.h"
#include "ball.h"
#include "SceneObject.h"
#include "PastyCam.h"
#include "manipulator.h"

#include <siut/simd/Vec2i.hpp>

using namespace TorPhysix;

#define MAX_BALLS 3*3*2
#define MAX_BOXES 64

class App : public GLFWApp
{
public:
	App();
	~App();
	void update(); // update physics
	void render();

	void resetCamera();
	void resetPhysics(); // reset objects to original state
	

private:
	struct PerfTimers{
		double render;
		double renderAccum;

		double genContacts;
		double genContactsAccum;

		double update;
		double updateAccum;

		int samples;
	};

	PerfTimers myPerfTimers;

	PastyCam myCamera;
	bool cameraMoveable;

	Manipulator myManipulator;
	bool doSelectionOnRender;
	siut::simd::Vec2i selectionTarget;

	int stepOneFrame;
	int simIterations;
	bool simRunning;

	const static unsigned maxContacts = (MAX_BALLS+MAX_BOXES)*8;
	TorPhysix::Contact contacts[maxContacts];

	TorPhysix::CollisionData cData;
	TorPhysix::ContactResolver resolver;
	std::vector<TorPhysix::PhysicsObject*> physObjList;
	std::vector<TorPhysix::Ball*> ballList;
	std::vector<TorPhysix::Box*> boxList;
	std::list< SceneObject* > sceneObjects;
	float lightPosition[4];
	float quat[4];
	
	void generateContacts(); // use collision detector to generate contacts
	void updateObjects(real duration);
	
	void renderDebugInfo();
	void selectObjectUnderCursor();
	void setSelected( SceneObject *sceneObject );
	void applyManipulatorToSelected();
	void initGUI();

	void onMouseMove(const int x, const int y, const int deltaX, const int deltaY);
	void onMouseButton(const int x, const int y, const int button, const bool pressed);
	void onKey(const int key, const bool pressed);
	void onSize(const int w, const int h);
	void onClose();

};